/*************************************************************************
	> File Name: connect.h
	> Author: xuwenlong
	> Mail: myxuan475@126.com
	> Created Time: 2018年01月22日 星期一 15时27分51秒
 ************************************************************************/
#ifndef FOUNDATION_DOWNLINK_CONNECTION_H
#define FOUNDATION_DOWNLINK_CONNECTION_H

#include <utils/lock.h>
#include <vector>
#include <functional>
#include <mutex>
#include <utils/logger.h>
#include "dbms_channel.h"
#include <uv.h>
#include <fcntl.h>
#include <unistd.h>

#define DC_USE_THREAD 1

namespace downlink {

class DownlinkConnect {
public:
	DownlinkConnect(const dbms::DeviceChannel_t &dc);
	virtual ~DownlinkConnect();

	static std::shared_ptr<DownlinkConnect> ConnectFactory(
		const dbms::DeviceChannel_t &dc);

	bool Send(uv_loop_t *uvLoop, const uint8_t cmd[], int len);
	void OnReceive(const std::function<void(uint8_t *, int)> &func);
	void OnError(std::function<void(int32_t)> onError);
	void Stop();
	bool IsFinished() const;

protected:
	virtual const std::string Name() const = 0;
	virtual bool ReConnect() = 0;
	virtual bool Send(const uint8_t cmd[], int32_t len) = 0;
	virtual void CloseConnect() = 0;
	virtual int32_t Recv(uint8_t cmd[], int32_t max, int32_t timeout = -1) = 0;
	virtual int32_t Handle() = 0;
	virtual bool IsAvailable() = 0;
	void OnEvents(int32_t status, int32_t events);
	void OnStop();

private:
	std::mutex chnnelMutex_;
	int timeout_;

#if DC_USE_THREAD == 0
	uv_poll_t poll_;
#endif
	std::function<void(uint8_t *, int)> onReceive_ = nullptr;
	std::function<void(int32_t)> onError_ = nullptr;
	bool isFinished_ = false;
};
}; // namespace downlink

#endif
